home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / QuickDraw / Band Copying the Sequel / Band Copying the Sequel.c next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  10.6 KB  |  377 lines  |  [TEXT/KAHL]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    Band Copying the Sequel                                    */
  4. /*                                                                            */
  5. /*    File:            Band Copying the Sequel.π                                */
  6. /*                    Band Copying the Sequel.c                                */
  7. /*                    Band Copying the Sequel.π.rsrc                            */
  8. /*                                                                            */
  9. /*    Description:    Under low memory conditions, it's often necessary        */
  10. /*                    to draw an image by individual bands rather than        */
  11. /*                    to draw the entire image at once, and in most cases        */
  12. /*                    this method works fine unless the image requires        */
  13. /*                    dithering from its source to its destination.  The        */
  14. /*                    purpose of this app is to show the problem that may        */
  15. /*                    occur when copying these individual bands and to        */
  16. /*                    provide one possible solution.                            */
  17. /*                                                                            */
  18. /*    Programmer:        Edgar Lee                                                */
  19. /*    Organization:    Apple Computer, Inc.                                    */
  20. /*    Department:        Developer Technical Support, DTS                        */
  21. /*    Language:        C (Think C version 5.0.1)                                */
  22. /*    Date Created:    11-03-91                                                */
  23. /*                                                                            */
  24. /****************************************************************************/
  25.  
  26. /* Constant Declarations */
  27.  
  28. #define    WWIDTH        300        /* Window width for the color and b/w images. */
  29. #define    WHEIGHT        300        /* Window height for the color and b/w images. */
  30.  
  31. #define WLEFT        (((screenBits.bounds.right - screenBits.bounds.left) - WWIDTH) / 2)
  32. #define WTOP        (((screenBits.bounds.bottom - screenBits.bounds.top) - WHEIGHT) / 2)
  33.  
  34. #define TOTALBANDS    25        /* Total number of bands to separate Pict into. */
  35. #define    PADHEIGHT    8        /* Padding to add above band in pixels. */
  36. #define    SCALING        4        /* Scale source by factor of... */
  37.  
  38. /* Global Variable Definitions */
  39.  
  40. WindowPtr        gCWindow;
  41. WindowPtr        gWindow;
  42.  
  43. GWorldPtr        gGWorld;
  44. PixMapHandle    gPixMap;
  45.  
  46. PicHandle        gPict;                /* Pict resource used for test. */
  47. int                gPictWidth;            /* Width of pict resource. */
  48. int                gPictHeight;        /* Height of pict resource. */
  49. int                gBandStart;            /* Starting band number to draw. */
  50. int                gBandEnd;            /* Ending band number to draw. */
  51. int             gBandHeight;        /* Thickness of band in pixels. */
  52. int                gPadding = 0;        /* Current value of padding. */
  53.  
  54. void initMac();            /* Initializes the environment. */
  55. void initPictInfo();    /* Initializes the picture information. */
  56.  
  57. void createWindows();    /* Creates windows for color and b/w images. */
  58. void createGWorld();    /* Creates 1 bit offscreen GWorld used for dithering. */
  59. void drawCWindow();        /* Displays the original color image. */
  60. void drawBwWindow();    /* Displays the dithered/enlarged b/w image. */
  61. void doBandCopy();        /* Copies image by individual bands. */
  62. void doNoBandCopy();    /* Copies the entire image at once without bands. */
  63. void drawMessage();        /* Draws text in color window. */
  64.  
  65. void doEventLoop();        /* Handles all events. */
  66.  
  67. main()
  68. {
  69.     initMac();
  70.     initPictInfo();
  71.  
  72.     createWindows();
  73.     createGWorld();
  74.     
  75.     doEventLoop();
  76. }
  77.  
  78. void initMac()
  79. {
  80.     MaxApplZone();
  81.     
  82.     InitGraf( &thePort );
  83.     InitFonts();
  84.     InitWindows();
  85.     InitMenus();
  86.     TEInit();
  87.     InitDialogs( nil );
  88.     InitCursor();
  89.     FlushEvents( 0, everyEvent );    
  90. }
  91.  
  92. void initPictInfo()
  93. {
  94.     gPict = (PicHandle)GetResource( 'PICT', 128 );
  95.  
  96.     gPictWidth = (**gPict).picFrame.right - (**gPict).picFrame.left;
  97.     gPictHeight = (**gPict).picFrame.bottom - (**gPict).picFrame.top;
  98.     
  99.     gBandStart = 0;                                /* Start at band number 0. */
  100.     gBandEnd = 0;                                /* End at band number 0. */
  101.     gBandHeight = gPictHeight / TOTALBANDS;
  102. }
  103.  
  104. void createWindows()
  105. {
  106.     Rect rect;
  107.     
  108.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  109.     
  110.     OffsetRect( &rect, -((WWIDTH + 10) / 2), 0 );
  111.     gCWindow = NewCWindow( 0L, &rect, "\pBand Copying the Sequel", true, documentProc,
  112.                             (WindowPtr)-1L, false, 0L );
  113.     
  114.     OffsetRect( &rect, WWIDTH + 10, 0 );
  115.     gWindow = NewCWindow( 0L, &rect, "\pBandCopying ON - Padding OFF", true, documentProc,
  116.                             (WindowPtr)-1L, true, 0L );
  117.                             
  118.     SetPort( gCWindow );
  119. }
  120.  
  121. void createGWorld()
  122. {
  123.     int        i;
  124.     Rect    rect;
  125.     
  126.     /* Create a 1bit offscreen gWorld to be used for B/W dithering. */
  127.  
  128.     NewGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, 0 );
  129.     gPixMap = GetGWorldPixMap( gGWorld );
  130. }
  131.  
  132. void drawCWindow()
  133. {
  134.     Rect    rect;
  135.     int        row;
  136.     
  137.     /* Reposition the picture's rect then draw it into the first window. */
  138.     
  139.     SetPort( gCWindow );
  140.     
  141.     rect.left = (WWIDTH - gPictWidth) / 2;
  142.     rect.top = (WHEIGHT - gPictHeight) / 2;
  143.     rect.right = rect.left + gPictWidth;
  144.     rect.bottom = rect.top + gPictHeight;
  145.     
  146.     DrawPicture( gPict, &rect );
  147.     
  148.     TextFont( helvetica );
  149.     TextSize( 12 );
  150.     
  151.     row = 20;    
  152.     drawMessage( &row, "\p• Click the mouse button in the" );
  153.     drawMessage( &row, "\p   b/w window to draw another band." );
  154.     drawMessage( &row, "\p• Press any key other than ESC to toggle between" );
  155.     drawMessage( &row, "\p   using band copying with or without padding." );
  156.     
  157.     row = 200;    
  158.     drawMessage( &row, "\p• Press ESC to toggle between using copybits" );
  159.     drawMessage( &row, "\p   with or without bands." );
  160. }
  161.  
  162. void drawMessage( row, string )
  163. int        *row;
  164. Str255    string;
  165. {
  166.     MoveTo( 10, *row += 15 );
  167.     DrawString(  string );
  168. }
  169.  
  170. void drawBwWindow()
  171. {
  172.     Rect rect;
  173.     
  174.     if (gPadding >= 0)
  175.     {
  176.         SetRect( &rect, 0, 0, gPictWidth * SCALING, (gBandHeight + gPadding) * SCALING );
  177.         UpdateGWorld( &gGWorld, 1, &rect, nil, nil, stretchPix );
  178.         gPixMap = GetGWorldPixMap( gGWorld );
  179.         doBandCopy();
  180.     }
  181.     else
  182.     {
  183.         UpdateGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, stretchPix );
  184.         gPixMap = GetGWorldPixMap( gGWorld );
  185.         doNoBandCopy();
  186.     }
  187. }
  188.  
  189. void doBandCopy()
  190. {
  191.     int            i;
  192.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  193.     Rect        colorRect;            /* Source rect for the color image band. */
  194.     Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  195.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  196.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  197.     GDHandle    currentGDevice;        /* GDevice used by window. */
  198.     Str255        string;
  199.         
  200.     hoffset = (WWIDTH - gPictWidth) / 2;
  201.     voffset = (WHEIGHT - gPictHeight) / 2;
  202.  
  203.     SetPort( gWindow );
  204.     TextFont( helvetica );
  205.     TextSize( 9 );
  206.  
  207.     GetGWorld( ¤tPort, ¤tGDevice );
  208.  
  209.     for (i = gBandStart; i <= gBandEnd; i++)
  210.     {
  211.         SetGWorld( gGWorld, nil );
  212.  
  213.         /* Define the source band rect for the color image, */
  214.         /*    INCLUDING any padding if applicable.            */
  215.         colorRect.left = hoffset;
  216.         colorRect.right = hoffset + gPictWidth;
  217.         colorRect.top = voffset + (i * gBandHeight) - gPadding;
  218.         colorRect.bottom = voffset + (i * gBandHeight) + gBandHeight;
  219.         
  220.         /* Define the destination band rect for the gworld dithered image, */
  221.         /*    allow extra space for padding if necessary.                       */
  222.         SetRect( &gworldRect, 0, 0, gPictWidth * SCALING,
  223.                             (gBandHeight + gPadding) * SCALING );
  224.     
  225.         /* Copy the color source into the B/W gworld using dithering. */
  226.         /*  Also, be sure to copy any padded area as well.              */
  227.         CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &gworldRect, ditherCopy, 0l);
  228.         
  229.         SetGWorld( currentPort, currentGDevice );
  230.         
  231.         /* Now, set the source band rect to the gworld image's EXCLUDING any padding. */
  232.         /*  If padding was used, offset pass the padding and down to the band.        */
  233.         SetRect( &gworldRect, 0, gPadding * SCALING, gPictWidth * SCALING,
  234.                                 (gPadding + gBandHeight) * SCALING );
  235.         
  236.         /* Define the destination band rect for the final b/w image. */
  237.         /*  No padding should apply here!!                             */
  238.         SetRect( &bwRect, hoffset / SCALING,
  239.                         (voffset / SCALING) + ((i * gBandHeight) * SCALING),
  240.                         (hoffset / SCALING) + (gPictWidth * SCALING),
  241.                         (voffset / SCALING) + (((i * gBandHeight) + gBandHeight) * SCALING) );
  242.  
  243.         /* Finally, copy the offscreen image into the B/W window. */
  244.         CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &gworldRect, &bwRect, srcCopy, 0l);
  245.     
  246.         SetPort( gWindow );
  247.         MoveTo( bwRect.right + 3, bwRect.bottom );
  248.         NumToString( i, &string );
  249.         DrawString( string );
  250.     }
  251. }
  252.  
  253. void doNoBandCopy()
  254. {
  255.     Rect        colorRect;            /* Source rect for the color image band. */
  256.     Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  257.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  258.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  259.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  260.     GDHandle    currentGDevice;        /* GDevice used by window. */
  261.     
  262.     GetGWorld( ¤tPort, ¤tGDevice );
  263.     
  264.     hoffset = (WWIDTH - gPictWidth) / 2;
  265.     voffset = (WHEIGHT - gPictHeight) / 2;
  266.  
  267.     colorRect.left = hoffset;
  268.     colorRect.top = voffset;
  269.     colorRect.right = hoffset + gPictWidth;
  270.     colorRect.bottom = voffset + gPictHeight;
  271.  
  272.     SetRect( &bwRect, hoffset / SCALING,
  273.                     voffset / SCALING,
  274.                     (hoffset / SCALING) + (gPictWidth * SCALING),
  275.                     (voffset / SCALING) + (gPictHeight * SCALING) );
  276.     
  277.     SetGWorld( gGWorld, nil );
  278.     CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &bwRect, ditherCopy, 0l);
  279.     SetGWorld( currentPort, currentGDevice );
  280.     CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &bwRect, &bwRect, srcCopy, 0l);
  281. }
  282.  
  283. void doEventLoop()
  284. {
  285.     EventRecord event;
  286.     WindowPtr   window;
  287.     short       clickArea;
  288.     Rect        screenRect;
  289.     static int    oldPadding;
  290.     
  291.     for (;;)
  292.     {
  293.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  294.         {
  295.             if (event.what == mouseDown)
  296.             {
  297.                 clickArea = FindWindow( event.where, &window );
  298.                 
  299.                 if (clickArea == inDrag)
  300.                 {
  301.                     screenRect = (**GetGrayRgn()).rgnBBox;
  302.                     DragWindow( window, event.where, &screenRect );
  303.                 }
  304.                 else if (clickArea == inContent)
  305.                 {
  306.                     if (window != FrontWindow())
  307.                         SelectWindow( window );
  308.                     else
  309.                     {
  310.                         if (gPadding >= 0)
  311.                         {    
  312.                             gBandEnd++;
  313.                             
  314.                             if (gBandEnd > TOTALBANDS)
  315.                             {
  316.                                 gBandEnd = 0;
  317.                                 SetPort( gWindow );
  318.                                 EraseRect( &gWindow->portRect );
  319.                             }
  320.                             
  321.                             gBandStart = gBandEnd;
  322.                             drawBwWindow();
  323.                         }
  324.                     }
  325.                 }
  326.                 else if (clickArea == inGoAway)
  327.                     if (TrackGoAway( window, event.where ))
  328.                         return;
  329.             }
  330.             else if (event.what == keyDown || event.what == autoKey)
  331.             {
  332.                 if ((event.message & charCodeMask) == 0x1b)
  333.                 {
  334.                     SetPort( gWindow );
  335.                     EraseRect( &gWindow->portRect );
  336.                     
  337.                     if (gPadding >= 0)
  338.                         gPadding = -1;
  339.                     else
  340.                         gPadding = oldPadding;
  341.                 }
  342.                 
  343.                 if (gPadding == 0)
  344.                 {
  345.                     gPadding = PADHEIGHT;
  346.                     SetWTitle( gWindow, "\pBandCopying ON - Padding ON" );
  347.                     oldPadding = 0;
  348.                 }
  349.                 else if (gPadding > 0)
  350.                 {
  351.                     gPadding = 0;
  352.                     SetWTitle( gWindow, "\pBandCopying ON - Padding OFF" );
  353.                     oldPadding = PADHEIGHT;
  354.                 }
  355.                 else
  356.                     SetWTitle( gWindow, "\pBandCopying OFF" );
  357.                     
  358.                 gBandStart = 0;
  359.                 drawBwWindow();
  360.             }
  361.             
  362.             else if (event.what == updateEvt)
  363.             {
  364.                 window = (WindowPtr)event.message;    
  365.                 SetPort( window );
  366.                 
  367.                 BeginUpdate( window );
  368.                 
  369.                 gBandStart = 0;
  370.                 drawCWindow();
  371.                 drawBwWindow();
  372.                 
  373.                 EndUpdate( window );
  374.             }
  375.         }
  376.     }
  377. }